package cn.pconline.autoclub.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Hashtable;
import javax.imageio.ImageIO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QrCodeUtil {
    private static final int BLACK = MatrixToImageConfig.BLACK;  
    private static final int WHITE = MatrixToImageConfig.WHITE;
    
    private static final Logger log = LoggerFactory.getLogger(QrCodeUtil.class);
    
    public static void main(String[] args) {
        System.out.println(QrCodeUtil.class.getResource("/car.png"));
        
        File logo = new File("F:/club_icon.png");
        System.out.println(logo + ": " + logo.canRead());
        try {
            ImageIO.read(logo);
        } catch (IOException e1) {
            log.error("",e1);
        }
        String content = "http://club.pcauto.com.cn/fff_club/?action=pcautoclub://club-detail/1054";
        
        File logoQrcode = new File("F:/logo-qr.jpg");
        qrcode2File(content, 200, logoQrcode, logo);
        
        String url = decode(logoQrcode);
        System.out.println("content: " + url);
        String s = String.format("http://club.pcauto.com.cn/%s/?action=pcautoclub://club-detail/%d", "fff_club", 1054);
        System.out.println(s);
    }
    
    public static void qrcode2File(String content, int width, File output, String logoPath){
        qrcode2File(content, width, output, new File(logoPath));
    }
    
    /**  
     * 生成QRCode二维码 
     */  
    public static void qrcode2File(String content, int width, File output, File logo){  
        try {
            Hashtable<EncodeHintType, Object> hints = setQrcodeHints(width);
              
            BitMatrix bitMatrix = new MultiFormatWriter().encode(content,BarcodeFormat.QR_CODE,width, width, hints);  
            
            boolean isLogo = false;
            if(logo != null) {
                isLogo = logo.exists();
            }
            writeToFile(bitMatrix, "jpg", output, isLogo, logo);  
        } catch (Exception e) {
            e.printStackTrace();  
        }
    }

    private static Hashtable<EncodeHintType, Object> setQrcodeHints(int width) {
        Hashtable<EncodeHintType,Object> hints = new Hashtable<EncodeHintType,Object>();  
        /*设置纠错级别(L 7%~M 15%~Q 25%~H 30%),纠错级别越高存储的信息越少*/
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);  
        /*设置编码格式*/
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");  
        /*设置边缘空白*/  
        hints.put(EncodeHintType.MARGIN, 1);
        hints.put(EncodeHintType.MAX_SIZE, width);
        hints.put(EncodeHintType.MIN_SIZE, width);
        return hints;
    }
    
    public static void qrcode2Stream(String content, int width, OutputStream output, String logoPath) {
        qrcode2Stream(content, width, output, new File(logoPath));
    }
    public static void qrcode2Stream(String content, int width, OutputStream output, File logo) {
        try {
            Hashtable<EncodeHintType, Object> hints = setQrcodeHints(width);
              
            BitMatrix bitMatrix = new QRCodeWriter().encode(content,BarcodeFormat.QR_CODE,width, width, hints);  
            
            boolean isLogo = false;
            if(logo != null && logo.isFile()) {
                isLogo = logo.exists();
            }
            writeToStream(bitMatrix, "png", output, isLogo, logo);  
        } catch (Exception e) {
            e.printStackTrace();  
        }
    }
    
    public static void writeToStream(BitMatrix bitMatrix, String format, OutputStream output, boolean isLogo, File logo) {
        BufferedImage bi = toBufferedImageContents(bitMatrix);
        try {
            if(isLogo){
                addRoundCornerLogo(bi, logo);
            }
            ImageIO.write(bi, format, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    /**
     * 添加logo
     * @param bi
     * @param logo
     * @throws IOException
     */
    public static void addLogo(BufferedImage bi, File logo)
            throws IOException {
        if(logo == null || !logo.exists()) {
            log.warn("logo is not found: {}", logo);
            return;
        }
        
        /*读取logo图片信息*/  
        Image logoImg = ImageIO.read(logo);//实例化一个Image对象。  
        /*当前图片的宽与高*/  
        int logoWidth = logoImg.getWidth(null);  
        int logoHeight = logoImg.getHeight(null);
        log.debug("logoImgWidth: {}, logoImgHeight: {};", logoWidth, logoHeight);
        int width = bi.getWidth();
        int height = bi.getHeight();
        int width_4 = width / 4;
        int logoX = width_4 + width_4 / 2; //(width - logoWidth) /2;
        int height_4 = height / 4;
        int logoY = height_4 + height_4 / 2; //(height - logoHeight) / 2;
        log.debug("width: {}, height: {}; x: {}, y: {}", width_4, height_4, logoX, logoY);
        /*返回由指定矩形区域定义的子图像*/
        BufferedImage bi2 = bi.getSubimage(logoX, logoY, width_4, height_4);
        /*获取一个绘图工具笔*/
        Graphics2D g2 = bi2.createGraphics();
        
        /*处理图片的宽与高*/
        int resultImgWidth = logoWidth;
        int resultImgHeight = logoHeight;
        if(logoWidth != width_4){
            resultImgWidth = width_4;
        }  
        if(logoHeight != height_4){
            resultImgHeight = height_4;
        }
        
        log.debug("logoWidth: {}, logoHeight: {};", resultImgWidth, resultImgHeight);
        /*绘制图片*/
        g2.drawImage(logoImg, 0, 0, resultImgWidth, resultImgHeight, null);
        //g2.drawImage(logoImg, 0, 0, logoWidth, logoHeight, null);
        g2.dispose();
        bi.flush();
    }
    
    /**
     * 添加圆角log
     * @param bi
     * @param logo
     * @throws IOException
     */
    public static void addRoundCornerLogo(BufferedImage bi, File logo)
            throws IOException {
        if(logo == null || !logo.exists()) {
            log.warn("logo is not found: {}", logo);
            return;
        }
        int width = bi.getWidth();
        int height = bi.getHeight();
        /*读取logo图片信息*/  
        Image logoImg = ImageIO.read(logo);//实例化一个Image对象。  
        /*当前图片的宽与高*/  
        int logoWidth = logoImg.getWidth(null);  
        int logoHeight = logoImg.getHeight(null);
        log.debug("logoImgWidth: {}, logoImgHeight: {};", logoWidth, logoHeight);
        int width_4 = width / 4;
        int logoX = width_4 + width_4 / 2; //(width - logoWidth) /2;
        int height_4 = height / 4;
        int logoY = height_4 + height_4 / 2; //(height - logoHeight) / 2;
        log.debug("width: {}, height: {}; x: {}, y: {}", width_4, height_4, logoX, logoY);
        /*返回由指定矩形区域定义的子图像*/
        //BufferedImage bi2 = bi.getSubimage(logoX, logoY, width_4, height_4);
        //设置圆角
        //bi2 = makeRoundedCorner(bi2, 20);
        /*获取一个绘图工具笔*/
        Graphics2D g2 = bi.createGraphics();
        /*处理图片的宽与高*/
        int resultImgWidth = logoWidth;
        int resultImgHeight = logoHeight;
        if(logoWidth != width_4){
            resultImgWidth = width_4;
        }  
        if(logoHeight != height_4){
            resultImgHeight = height_4;
        }
        
        log.debug("logoWidth: {}, logoHeight: {};", resultImgWidth, resultImgHeight);
        /*绘制图片*/
        g2.drawImage(logoImg, logoX, logoY, resultImgWidth, resultImgHeight, null);
        g2.setStroke(new BasicStroke(3f));
        Shape shape = new RoundRectangle2D.Float(logoX, logoY, resultImgWidth, resultImgHeight, 10, 10);
        //g2.setColor(Color.BLACK); //默认是白色
        g2.draw(shape);
        g2.dispose();
        bi.flush();
    }
    
    public static void writeToFile(BitMatrix bitMatrix, String format, boolean isLogo, File logo, String targetPath) throws IOException {
        writeToStream(bitMatrix, format, new FileOutputStream(targetPath), isLogo, logo);
    }

    /**  
     * 生成二维码图片  
     * @param bitMatrix   
     * @param format 图片格式  
     * @param file  生成二维码图片位置  
     * @param isLogo 是否要加logo图  
     * @param logo logo图片  
     * @throws IOException   
     */  
    public static void writeToFile(BitMatrix bitMatrix, String format, File file, boolean isLogo, File logo) throws IOException {
        BufferedImage bi = toBufferedImageContents(bitMatrix);
        if(isLogo){
            addRoundCornerLogo(bi, logo);
        }
        ImageIO.write(bi, format, file);  
    }  
    /**  
     * 生成二维码内容  
     * @param bitMatrix  
     * @return  
     */  
    public static BufferedImage toBufferedImageContents(BitMatrix bitMatrix){
        int width = bitMatrix.getWidth();  
        int height = bitMatrix.getHeight();  
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) == true ? BLACK : WHITE);
            }
        }
        return image;  
    }
    
    /**  
     * 解析二维码  
     * @param path 图片的绝对路径  
     */  
    public static String decode(File qrCodeFile){
        if (qrCodeFile == null || !qrCodeFile.exists()) {
            log.error("二维码文件不存在");
            return null;
        }
        BufferedImage image = null;
        try {
            image = ImageIO.read(qrCodeFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        /* 判断是否是图片 */
        if (image == null) {
            log.error("不能读取图片文件");
            return null;
        }
        /* 解析二维码用到的辅助类 */
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
        /* 解码设置编码方式为：UTF-8 */
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
        try {
            Result result = new MultiFormatReader().decode(bitmap, hints);
            String resultStr = result.getText();
            return resultStr;
        } catch (NotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}